package com.rpframework.module.common.bottom.api.baidu.com;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedHashMap;
import java.util.Map;

import static com.rpframework.module.common.bottom.api.baidu.com.Config.SK;
import static com.rpframework.utils.URLUtils.toQueryString;

/**
 * java版计算signature签名
 */
public class SnCal {
    public static void main(String[] args) throws UnsupportedEncodingException,
            NoSuchAlgorithmException {

        // 计算sn跟参数对出现顺序有关，所以用LinkedHashMap保存<key,value>，此方法适用于get请求，
        // 如果是为发送post请求的url生成签名，请保证参数对按照key的字母顺序依次放入Map。以get请求为例：
        // http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourAk，paramsMap中先放入address，
        // 再放output，然后放ak，放入顺序必须跟get请求中对应参数的出现顺序保持一致。
        Map<String, Object> paramsMap = new LinkedHashMap<>();
        paramsMap.put("location", "30.548397,104.04701");
        paramsMap.put("output", "json");
        paramsMap.put("ak", "L8rtMV1Gbx2VGPBir4NkOlV4iZyOv56O");

        // 调用下面的toQueryString方法，对LinkedHashMap内所有value作utf8编码，拼接返回结果address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourAk
        String paramsStr = toQueryString(paramsMap);

        // 对paramsStr前面拼接上/geocoder/v2/?，后面直接拼接yourSk得到/geocoder/v2/?address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourAkYourSk
        String wholeStr = "/geocoder/v2/?" + paramsStr + "EC7Hfn45HCrgPGER3VjOALp7OIBrTk3R";

        // 对上面wholeStr再作utf8编码
        String tempStr = URLEncoder.encode(wholeStr, "UTF-8");

        // 调用下面的MD5方法得到最后的sn签名7de5a22212ffaa9e326444c75a58f9a0
        System.out.println(MD5(tempStr));
        System.out.println(getSn(paramsMap, "/geocoder/v2/"));
    }

    /**
     * 获取SK
     *
     * @param paramsMap 参数
     * @param uri       URI
     * @return AK
     */
    private static String getSn(Map<String, Object> paramsMap, String uri, String sk) {
        String q;
        try {
            q = toQueryString(paramsMap);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        q = uri + "?" + q + sk;
        try {
            q = URLEncoder.encode(q, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        return MD5(q);
    }

    /**
     * {@Link}getSn + 配置文K
     */
    static String getSn(Map<String, Object> paramsMap, String uri) {
        return getSn(paramsMap, uri, SK);
    }

    /**
     * 来自stackOverflow的MD5计算方法，
     * 调用了MessageDigest库函数，并把byte数组结果转换成16进制*
     *
     * @param md5 加密
     * @return byte数组结果转换成16进制
     */
    public static String MD5(String md5) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest
                    .getInstance("MD5");
            byte[] array = md.digest(md5.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte anArray : array) {
                sb.append(Integer.toHexString((anArray & 0xFF) | 0x100)
                        .substring(1, 3));
            }
            return sb.toString();
        } catch (java.security.NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}